﻿using System.Diagnostics;
using System.Xml.Linq;
using X = Adjunct.Framework.Nuspec.XNames.Package.Metadata;

namespace Adjunct.Framework.Nuspec
{
	/// <summary>
	/// 
	/// </summary>
	/// <remarks></remarks>
	[DebuggerDisplay("{Id}: {Version}")]
	public class NuspecMetadata
	{
		private NuspecDependencies _dependencies;
		private NuspecFrameworkReferences _frameworkReferences;
		private NuspecLibReferences _libReferences;

		/// <summary>
		/// Gets or sets the authors.
		/// </summary>
		/// <value>The authors.</value>
		/// <remarks></remarks>
		public string Authors { get; set; }

		/// <summary>
		/// Gets or sets the copyright.
		/// </summary>
		/// <value>The copyright.</value>
		/// <remarks></remarks>
		public string Copyright { get; set; }

		/// <summary>
		/// Gets or sets the dependencies.
		/// </summary>
		/// <value>The dependencies.</value>
		/// <remarks></remarks>
		public NuspecDependencies Dependencies
		{
			get { return _dependencies ?? (_dependencies = new NuspecDependencies()); }
			set { _dependencies = value; }
		}

		/// <summary>
		/// Gets or sets the description.
		/// </summary>
		/// <value>The description.</value>
		/// <remarks></remarks>
		public string Description { get; set; }

		/// <summary>
		/// Gets or sets the framework references.
		/// </summary>
		/// <value>The framework references.</value>
		/// <remarks></remarks>
		public NuspecFrameworkReferences FrameworkReferences
		{
			get { return _frameworkReferences ?? (_frameworkReferences = new NuspecFrameworkReferences()); }
			set { _frameworkReferences = value; }
		}

		/// <summary>
		/// Gets or sets the icon URL.
		/// </summary>
		/// <value>The icon URL.</value>
		/// <remarks></remarks>
		public string IconUrl { get; set; }

		/// <summary>
		/// Gets or sets the id.
		/// </summary>
		/// <value>The id.</value>
		/// <remarks></remarks>
		public string Id { get; set; }

		/// <summary>
		/// Gets or sets the language.
		/// </summary>
		/// <value>The language.</value>
		/// <remarks></remarks>
		public string Language { get; set; }

		/// <summary>
		/// Gets or sets the lib references.
		/// </summary>
		/// <value>The lib references.</value>
		/// <remarks></remarks>
		public NuspecLibReferences LibReferences
		{
			get { return _libReferences ?? (_libReferences = new NuspecLibReferences()); }
			set { _libReferences = value; }
		}

		/// <summary>
		/// Gets or sets a value indicating whether [license acceptance].
		/// </summary>
		/// <value><c>true</c> if [license acceptance]; otherwise, <c>false</c>.</value>
		/// <remarks></remarks>
		public bool LicenseAcceptance { get; set; }

		/// <summary>
		/// Gets or sets the license URL.
		/// </summary>
		/// <value>The license URL.</value>
		/// <remarks></remarks>
		public string LicenseUrl { get; set; }

		/// <summary>
		/// Gets or sets the owners.
		/// </summary>
		/// <value>The owners.</value>
		/// <remarks></remarks>
		public string Owners { get; set; }

		/// <summary>
		/// Gets or sets the project URL.
		/// </summary>
		/// <value>The project URL.</value>
		/// <remarks></remarks>
		public string ProjectUrl { get; set; }

		/// <summary>
		/// Gets or sets the release notes.
		/// </summary>
		/// <value>The release notes.</value>
		/// <remarks></remarks>
		public string ReleaseNotes { get; set; }

		/// <summary>
		/// Gets or sets the summary.
		/// </summary>
		/// <value>The summary.</value>
		/// <remarks></remarks>
		public string Summary { get; set; }

		/// <summary>
		/// Gets or sets the tags.
		/// </summary>
		/// <value>The tags.</value>
		/// <remarks></remarks>
		public string Tags { get; set; }

		/// <summary>
		/// Gets or sets the title.
		/// </summary>
		/// <value>The title.</value>
		/// <remarks></remarks>
		public string Title { get; set; }

		/// <summary>
		/// Gets or sets the version.
		/// </summary>
		/// <value>The version.</value>
		/// <remarks></remarks>
		public string Version { get; set; }

		/// <summary>
		/// Clones this instance.
		/// </summary>
		/// <returns></returns>
		/// <remarks></remarks>
		public NuspecMetadata Clone()
		{
			return new NuspecMetadata
			{
				Id = Id,
				Title = Title,
				Authors = Authors,
				Owners = Owners,
				Copyright = Copyright,
				Description = Description,
				Summary = Summary,
				Version = Version,
				ReleaseNotes = ReleaseNotes,
				Language = Language,
				ProjectUrl = ProjectUrl,
				IconUrl = IconUrl,
				LicenseUrl = LicenseUrl,
				LicenseAcceptance = LicenseAcceptance,
				Tags = Tags,
				Dependencies = Dependencies.Clone(),
				LibReferences = LibReferences.Clone(),
				FrameworkReferences = FrameworkReferences.Clone()
			};
		}

		/// <summary>
		/// Performs an explicit conversion from <see cref="Adjunct.Framework.Nuspec.NuspecMetadata"/> 
		/// to <see cref="System.Xml.Linq.XElement"/>.
		/// </summary>
		/// <param name="metadata">The metadata.</param>
		/// <returns>The result of the conversion.</returns>
		/// <remarks></remarks>
		public static explicit operator XElement(NuspecMetadata metadata)
		{
			return (metadata == null)
			       	? null
			       	: new XElement(X.ElementName,
			       	               metadata.Id.ToXElement(X.Id),
			       	               metadata.Title.ToXElementIfNotEmpty(X.Title),
			       	               metadata.Authors.ToXElement(X.Authors),
			       	               metadata.Owners.ToXElementIfNotEmpty(X.Owners),
			       	               metadata.Copyright.ToXElementIfNotEmpty(X.Copyright),
			       	               metadata.Description.ToXElement(X.Description),
			       	               metadata.Summary.ToXElementIfNotEmpty(X.Summary),
			       	               metadata.Version.ToXElement(X.Version),
			       	               metadata.ReleaseNotes.ToXElementIfNotEmpty(X.ReleaseNotes),
			       	               metadata.Language.ToXElementIfNotEmpty(X.Language),
			       	               metadata.ProjectUrl.ToXElementIfNotEmpty(X.ProjectUrl),
			       	               metadata.IconUrl.ToXElementIfNotEmpty(X.IconUrl),
			       	               metadata.LicenseUrl.ToXElementIfNotEmpty(X.LicenseUrl),
			       	               metadata.LicenseAcceptance.ToXElement(X.RequireLicenseAcceptance),
			       	               metadata.Tags.ToXElementIfNotEmpty(X.Tags),
			       	               (XElement)metadata.Dependencies,
			       	               (XElement)metadata.LibReferences,
			       	               (XElement)metadata.FrameworkReferences);
		}

		/// <summary>
		/// Performs an explicit conversion from <see cref="System.Xml.Linq.XElement"/> 
		/// to <see cref="Adjunct.Framework.Nuspec.NuspecMetadata"/>.
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>The result of the conversion.</returns>
		/// <remarks></remarks>
		public static explicit operator NuspecMetadata(XElement element)
		{
			if (element == null)
			{
				return null;
			}
			element.EnsureElementNameIs(X.ElementName);
			return new NuspecMetadata
			{
				Id = element.ChildElementValue(X.Id),
				Title = element.ChildElementValue(X.Title, null),
				Authors = element.ChildElementValue(X.Authors),
				Owners = element.ChildElementValue(X.Owners, null),
				Copyright = element.ChildElementValue(X.Copyright, null),
				Description = element.ChildElementValue(X.Description),
				Summary = element.ChildElementValue(X.Summary, null),
				Version = element.ChildElementValue(X.Version),
				ReleaseNotes = element.ChildElementValue(X.ReleaseNotes, null),
				Language = element.ChildElementValue(X.Language, null),
				ProjectUrl = element.ChildElementValue(X.ProjectUrl, null),
				IconUrl = element.ChildElementValue(X.IconUrl, null),
				LicenseUrl = element.ChildElementValue(X.LicenseUrl, null),
				LicenseAcceptance = element.Element(X.RequireLicenseAcceptance).ValueAsBool(false),
				Tags = element.ChildElementValue(X.Tags, null),
				Dependencies = (NuspecDependencies)element.Element(X.Dependencies.ElementName),
				LibReferences = (NuspecLibReferences)element.Element(X.References.ElementName),
				FrameworkReferences = (NuspecFrameworkReferences)element.Element(X.FrameworkAssemblies.ElementName)
			};
		}
	}
}